#ifndef SYSTEM_H_
#define SYSTEM_H_

#include "FileSystem.h"
#include <vector>
#include <map>

#define READ 1
#define WRITE 2

#define MAX_SFLINK_DEPTH 10

typedef struct {
	int position;
	int permissions;
	int inode;
	int num_references;
} OpenFile;

typedef struct {
	bool read_only; //when true, only read is allowed
	bool fully_locked; //when true, only locking thread may read/write
	pthread_t lockingThreadId;
} LockData;

class System
{
private:
	FileSystem* fs;

	OpenFile openFiles[128];
	vector<int> freeEntries;

	map<int, LockData*> locks;

	pthread_mutex_t	m_FileSystemMutex;

	int create(const char* filename, int type);
	int getInode(const char* fullPath);
	int getParentDirInode(const char* filename);

public:
	System(FileSystem* fs);
	virtual ~System();

	int incReferenceCount(int fd);
	int decReferenceCount(int fd);

	void status();

	int RmDir_r(const char* dirname);

	int full(int dir, int s);

	// - creates and opens a new file named ‘file_name’ returning a fd to the new file.
	//If type is soft-link mark it as such. Opens the file with the specified permissions.
	int MakeFile(const char* filename, int type, int access_permissions);

	// - creates a hard link with name file-name, linked to target.
	int MakeHLink(const char* target, const char*linkname);

	// - creates a new directory named ‘dir-name’
	int MakeDir(const char* dirname);

	// - lists the content of the location-directory. Return list in buf.
	int ls(const char* dirname);
	int ls(const char*dirname, char* buf);

	// - removes the directory ‘dir-name’
	int RmDir(const char* dirname);

	// - removes the file ‘file-name’
	int RmFile(const char* filename);

	//opens the file ‘file-name’. Needs to deal with soft-links.
	//Opens the file with the specified permissions.
	int Open(const char* filename, int permissions, int sflink_depth);

	// - closes the entry of the file in the file table, and frees the entry in the fd table.
	int Close(int fd);

	// - moves the file curser to ‘location’.
	int Seek(int fd, int location);

	// - reads nBytes from the received file into the buffer.
	int Read (int fd, int nBytes, byte* buffer);

	// - writes nBytes from buffer into the file.
	int Write (int fd, int nBytes, const byte* buffer);

	// - moves the file oldName to newName.
	//This function allows moving files to different directories and \ or change the files name.
	int moveFile(const char* oldName, const char* newName);

	// - Returns whether this address is a directory or not. Needs to deal with soft-links.
	bool isDir(const char * address);

	// locks file, so that only read operations are allowed.
	//There is no limit on the number of processes that are allowed to concurrently read the file.
	//No processes are allowed to write to the file if there is an open read lock on the file.
	//It is not obligatory to lock the file to read it.
	//You should not block if it is locked rather return an error.
	int lockRead(int fd);

	//locks file, so that only one process may hold the lock.
	//This process may write to the file, and no other files may write to it or read from it.
	//A child does not inherit this lock. It is not obligatory to lock the file to write to it.
	//You should not block if it is locked rather return an error
	int lockWrite(int fd);

	//releases the reading lock held by this process.
	//Only the process which locked the file may release the lock.
	int releaseLockRead(int fd);

	// -releases the writing lock held by this process.
	//Only the process that locked the file may release this lock.
	int releaseLockWrite(int fd);

};

#endif /*SYSTEM_H_*/
